package cn.itsource.string;

import java.util.Arrays;

/**
 *	字符串相关的类：
 *		1. String 字符串类，底层是基于char[], 一旦创建长度就固定不变了,适用于字符串不经常增删改的操作的场景。父接口：CharSequence
 *			该接口的实现类：String、StringBuffer、StringBuilder
 *		String str = "abc";
 *		str += "d";//会创建新对象
 *		
 *		2. 将其他类型转换为String类型的方式效率问题：
 *			toString() > String.valueOf(Object obj); > +
 *			因为+号，底层先将字符串对象转换为StringBuilder对象，然后调用StringBuilder对象的append追加字符串方法，再调用toString方法
 *			转换为String对象
 *
 *		3. 拼接字符串效率最高的方式：
 * 			StringBuilder.append() > StringBuffer.append() > +
 *
 *			如果经常操作字符串用StringBuilder和StringBuffer，如果是单线程或者多线程且不要求线程安全问题，用StringBuilder，
 * 			如果是多线程且是线程安全要求用StringBuffer
 * 
 * 		4. 字符串常量池：提高效率
 * 
 * 			放字符串常量的地方，JDK8后是放在堆中
 *
	 *		当创建字符串对象是字面量(直接是="")的时候，会优先从常量池中查找，是否有该字符串对象，如果有，则会直接将常量池中的地址赋值给该String对象，
	 *		如果没有，则会在常量池创建对象，然后将对象常量池的地址给String对象保存
	 *
	 *		当创建字符串对象用new创建，会优先从常量池中查找，是否有该字符串对象，如果有，则会直接将常量池中的地址赋值给该String对象在堆中的地址，
	 *		如果没有，则会在常量池创建对象，然后将对象常量池的地址给String对象在堆中保存
	 *
	 *		equals方法：
	 *			比较两个字符串对象是否相等
	 *		
	 *		不要这样写，因为，name是String类型，有可能是null，避免空指针异常
	 *		if(name.equals("波波")){
	 *			
	 *		}
	 *		应该这样写：
	 *		if("波波".equals(name)){
	 *			
	 *		}
	 *		
	 *		扩展：提高效率，不用每次判断条件的时候，去执行arr.length
	 *		for(int i = 0,int j = arr.length-1; i <= j; i++){
	 *
	 *		}
 *
 *	注意：
 *		常用字符集有：
 *			UTF-8（世界通用编码集）变长字符（占用字节：1-3个），GBK（中国）（英文数字1个，中文2个字节）
 */
public class StringTest2 {

	public static void main(String[] args) {
		String str = "123";//字面量，常量
		String str2 = "123";
		
		String str3 = new String("123");//只要是new都在堆中，在堆中创建新对象
		String str4 = new String("123");//在堆中创建新对象
		
		System.out.println(str == str2);//判断是否为同一个地址
		System.out.println(str2 == str3);
		System.out.println(str3 == str4);
		
		System.out.println(str.equals(str2));//判断两个对象字符串值是否相同
		System.out.println(str2.equals(str3));
		System.out.println(str3.equals(str4));
		
		//======================================
		str = str + "a";//会在常量池中新创建一个新的字符串常量，赋值给str保存
		String str5 = "123" + "a";//在编译器就会直接将这两个字符串拼接到一起
		String str6 = "123a";
		System.out.println(str5 == str6);
	}

}
